/*
 * Database.h
 *
 *  Created on: 13 Jul 2011
 *      Author: allan
 */

#ifndef DATABASE_H_
#define DATABASE_H_

// C++ includes
#include <list>
using namespace std;

// Boost includes
#include <boost/optional.hpp>
using boost::optional;

struct ReactionInfo
{
	/// The formula of the reactant in the reaction
	string reactant;
	
	/// The formulas of the products in the reaction 
	vector<string> products;
	
	/// The stoichiometries of the products in the reaction     
	vector<double> stoichiometries;
	
	/// The log10 of the equilibrium constants of the reaction over a set of temperature points
	vector<double> logKi;
	
	/// The temperature points where the equilibrium constants are interpolated       
	vector<double> Ti;
};

struct SpeciesInfo
{
	/// The formula of the species
	string formula;
	
	/// The name of the species
	string name;
	
	/// The molecular weight of the species
	double molecularWeight;
	
	/// The volumetric weight of the species
	double volumetricWeigth;
	
	/// The radius of the species
	double radius;
	
	/// The tags of the species
	vector<string> tags;
	
	SpeciesInfo() : molecularWeight(0), volumetricWeigth(0), radius(0) {}

	bool 
	HasTag(const string& tag) const { return std::find(tags.begin(), tags.end(), tag) != tags.end(); }
	
	bool 
	HasAnyTag(const vector<string>& tags) const { for(unsigned i = 0; i < tags.size(); ++i) if(HasTag(tags[i])) return true; return false; }
};

struct ComplexInfo
{
	/// The formula of the complex species
	string formula;
	
	/// The formulas of the ionic species that compose the complex 
	vector<string> ions;
	
	/// The stoichiometries of the ionic species that compose the complex
	vector<double> stoichiometries;
};

class Database
{
public:
	typedef list<ReactionInfo>
	ReactionInfoList;
	
	typedef list<SpeciesInfo>
	SpeciesInfoList;
	
	typedef list<ComplexInfo>
	ComplexInfoList;
	
public:
	static const Database& 
	GetInstance();
	
	const ReactionInfoList& 
	GetReactionInfoList() const;
	
	const SpeciesInfoList&
	GetSpeciesInfoList() const;
	
	const ComplexInfoList&
	GetComplexInfoList() const;
	
	const ReactionInfo
	GetReactionInfo(const string& reactant) const;
	
	const SpeciesInfo
	GetSpeciesInfo(const string& species) const;
	
	const ComplexInfo
	GetComplexInfo(const string& complex) const;
	
	const optional<ReactionInfo>
	FindReactionInfo(const string& reactant) const;
	
	const optional<SpeciesInfo>
	FindSpeciesInfo(const string& species) const;
	
	const optional<ComplexInfo>
	FindComplexInfo(const string& complex) const;
	
private:
	Database();
	Database(const string& filename);
	
private:
	/// The list of reaction's info
	ReactionInfoList reactions;
	
	/// The list of species' info
	SpeciesInfoList species;
	
	/// The list of complex's info
	ComplexInfoList complexes;
};

#endif /* DATABASE_H_ */
